<!-- 大号组件：列表 -->
<template>
  <u-skeleton :title="false" :loading="pageLoading" :rows="skeleton.rows" :rowsWidth="skeleton.rowsWidth" :rowsHeight="skeleton.rowsHeight">
    <view class="full">
      <view class="listSearch">
        <m-list-search :config="searchConfig" :search="search" @filter="showFilter" @search="handleSearch">
          <slot name="search" />
        </m-list-search>
      </view>
      <view class="m-list">
        <movable-area class="movable">
          <movable-view direction="all" :out-of-bounds="falseValue" class="r-b-btn">
            <slot name="btn" />
          </movable-view>
          <u-list @scrolltolower="loadNextPage" lowerThreshold="80" enableBackToTop enableFlex height="740" width="100%">
            <view class="u-list--box">
              <slot name="list" />
              <view class="list-image" v-if="loading.status !== 'loading' && !list.length">
                <view class="list-image__item">
                  <image src="../../static/index/empty.png" />
                  <text>暂无查询数据</text>
                </view>
              </view>
              <u-list-item v-for="(item, index) in list" :key="index" v-if="list.length">
                <u-checkbox-group placement="column" :modelValue="check" @change="(e) => changeCheck(e, index)">
                  <m-list-item
                    :config="item"
                    :checkMode="checkMode"
                    @listClick="handleList"
                    @btnClick="btnClick"
                    :index="index"
                    @mounted="mounted(index)"
                  >
                    <view class="pl-16" v-if="checkMode">
                      <u-checkbox size="28" iconSize="28" :key="index" :name="index"> </u-checkbox>
                    </view>
                  </m-list-item>
                </u-checkbox-group>
              </u-list-item>
              <!--列表数据的状态 -->
              <m-loading :config="loading" v-if="loading.status === 'loading' || list.length" />
            </view>
          </u-list>
        </movable-area>
      </view>
      <!-- 汇总 -->
      <view class="m-list__menu" v-if="checkMode">
        <view class="f row sb fs pad-20 h80">
          <view class="f row ac g">
            <u-checkbox-group @change="changeAll" v-model="isCheckAll"><u-checkbox size="18" name="all" /></u-checkbox-group>
            <text style="color: #5582f3" @click="changeSelect">全选</text>
            <view class="m-list__menu--txt">选中{{ check.length }}个，共{{ count }}个</view>
          </view>
          <m-btn :config="{ width: '240rpx', text: '收货', shape: 'circle' }" @btnClick="listConfirm" />
        </view>
      </view>
      <!-- 过滤筛选 -->
      <m-popup ref="searchPop" @open="open">
        <view class="m-list__box">
          <!-- 表单 -->
          <m-form :config="search" ref="filterForm" />
          <!-- 按钮：重置/筛选 -->
          <view class="m-list--btn f row mt-2">
            <u-button type="info" shape="circle" text="重置" @click="reset" />
            <u-button type="primary" shape="circle" text="确认" @click="confirmFilter" />
          </view>
        </view>
      </m-popup>
    </view>
  </u-skeleton>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, nextTick } from 'vue';
import { filterEmpty, debounce, reverseList } from '../../../mo-form/utils/tools';
import { onShow } from '@dcloudio/uni-app';
const pageLoading = ref(true);
const empFun = () => {};
const falseValue = ref(false);
const list: any = ref([]);
const page = ref({ page: 1, pageSize: 10 });
const loading: any = ref({ status: 'loading' });
const searchPop = ref();
const filterForm = ref<HTMLElement>();
const check: any = ref([]);
const isCheckAll: any = ref([]);
const props = defineProps({ config: Object });
const skeleton = computed(() => {
  if (!props.config?.skeleton) {
    console.warn('list组件未开启骨架屏配置，如需开启，请在config中设置skeleton');
  }
  return props.config?.skeleton ?? {};
});
const dao = computed(() => props.config?.dao ?? empFun); // 不需要是响应式数据，setup绑定一次
const count = ref(0);
const checkMode = computed(() => props.config?.checkMode ?? false);
const daoParams = computed(() => props.config?.daoParams ?? {});
const onloadParams = computed(() => props.config?.onloadParams ?? {});
const searchConfig = computed(() => props.config?.searchConfig ?? { placeholder: '请输入查询参数', query: 'search', value: '' });
const search = computed(() => props.config?.search ?? {}); //传入表单的配置
const filterModel = ref({});
const originModel = ref({});
const emit = defineEmits(['listClick', 'btnClick', 'finish', 'confirm', 'open', 'checkConfirm']);

onMounted(() => console.log('列表组件完成挂载'));
onShow(() => {
  originModel.value = initFilter();
  filterModel.value = { ...originModel.value };
  nextTick(() => getList(null));
});
// 获取下一页
async function getList(data: any) {
  try {
    loading.value.status = 'loading';
    loading.value.nomoreText = '加载完成';
    loading.value.loadingText = '正在加载...';
    const res = await dao.value(
      Object.assign(
        {},
        { ...page.value },
        filterEmpty(daoParams.value),
        filterEmpty(filterModel.value),
        {
          [searchConfig.value.query]: searchConfig.value.vlaue
        },
        filterEmpty(data)
      )
    );
    loading.value.loadingText = '加载更多';
    const { rows, count: c, others, _data } = res || {};
    // 或者count 变化的时候说明数据变了
    if (page.value.page === 1 || count.value !== c) {
      count.value = c;
      list.value = rows;
      if (list.value.length === count.value) {
        loading.value.status = 'nomore';
      }
    } else if (list.value.length < count.value) {
      count.value = c;
      list.value.push(...rows);
      if (list.value.length === count.value) loading.value.status = 'nomore';
    } else if (list.value.length === count.value) {
      count.value = c;
      page.value.page -= 1;
      loading.value.status = 'nomore';
      uni.showToast({ title: '加载完成', icon: 'none' });
    }
    setTimeout(() => (pageLoading.value = false), skeleton.value?.time ?? 500);
    emit('finish', { others, _data });
  } catch (e) {
    loading.value.status = 'nomore';
    loading.value.nomoreText = '加载失败';
    console.warn('list 数据接口报错', e);
  }
}
function initFilter() {
  if (search.value?.items) {
    return search.value.items.reduce((pre: Object, now: Object) => {
      Object.keys(now).forEach((k) => {
        if (k.includes(',') && now[k].value) {
          const a = k.split(',');
          pre[a[0]] = now[k].value[0];
          pre[a[1]] = now[k].value[1];
        } else if (now[k].value) {
          pre[k] = now[k].value;
        }
      });
      return pre;
    }, {});
  } else {
    return {};
  }
}
function loadNextPage() {
  page.value.page += 1;
  getList(null);
}
// 列表子项完成渲染
function mounted(e: any) {
  debounce(() => {
    console.log('完成render的列表id', e, count.value, list.value.length);
  }, 200);
}
function handleSearch(v: any) {
  searchConfig.value.vlaue = v;
  getList(null);
}
function showFilter() {
  if (!Object.keys(search.value).length) return console.error('没有配置筛选字段');
  searchPop.value.show();
}
function confirmFilter() {
  filterModel.value = filterForm.value?.get();
  getList(null);
  searchPop.value?.close();
  emit('confirm', filterModel.value);
}
// 点击列表
function handleList(e: any) {
  emit('listClick', { _p: { ...onloadParams.value }, ...e });
}
// 筛选条件重置
function reset() {
  filterForm.value?.reset(originModel.value);
}
function btnClick(e: any) {
  emit('btnClick', e);
}
function resetPager() {
  page.value.page = 1;
}
function changeCheck(e: Array<number>, idx: number) {
  if (e[0] !== undefined) {
    check.value.push(e[0]);
  } else {
    check.value = check.value.filter((x) => x !== idx);
  }
}
function changeAll(e) {
  if (e.length) {
    list.value.forEach((item: any, idx: number) => {
      if (!check.value.includes(idx)) check.value.push(idx);
    });
  } else {
    check.value = [];
  }
}
function listConfirm() {
  const emitValue = get().map((e: any) => reverseList(e));
  emit('checkConfirm', emitValue);
}
function open() {
  emit('open');
}
function set(params: Object) {
  filterForm.value.set(params);
}
function changeSelect() {
  isCheckAll.value.length ? isCheckAll.value.pop() : isCheckAll.value.push('all');
  changeAll(isCheckAll.value);
}
function get() {
  return check.value.reduce((pre: Array<any>, cur: number) => {
    pre.push(list.value[cur]);
    return pre;
  }, []);
}
defineExpose({ reset, resetPager, getList, set, get });
</script>
<style lang="scss">
.u-list--box {
  &:first-child {
    padding-top: 16rpx;
  }
  &:last-child {
    padding-bottom: 160rpx;
  }
}
.list-image {
  width: 100%;
  display: flex;
  justify-content: center;
  height: 600rpx;
  &__item {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    > image {
      width: 420rpx;
      height: 360rpx;
      margin: auto;
    }
    > text {
      width: 100%;
      text-align: center;
      color: #999999;
      transform: translateY(-60rpx) translateX(-10rpx);
    }
  }
}
.mt-2 {
  button {
    &:first-of-type {
      border-top-right-radius: 0 !important;
      border-bottom-right-radius: 0 !important;
    }
    &:last-of-type {
      border-top-left-radius: 0 !important;
      border-bottom-left-radius: 0 !important;
    }
  }
}
.full {
  width: 100%;
  height: 100vh;
  overflow: hidden;
}
.listSearch {
  width: 100%;
  position: fixed;
  top: 0;
  z-index: 10;
  background-color: #eeeeee;
}
.m-list {
  width: 100%;
  background-color: #eeeeee;
  margin-top: 80rpx;
  padding-bottom: 160rpx;
  &__menu {
    width: 100%;
    height: 160rpx;
    position: absolute;
    bottom: 0;
    background-color: #fff;
    border-top: 1rpx solid rgba($color: #000000, $alpha: 0.1);
    &--txt {
      height: 100%;
      color: #999999;
      padding-left: 20rpx;
      line-height: 66rpx;
    }
    &--btn {
      width: 200rpx;
      height: 60rpx;
    }
  }
  &__box {
    min-height: 500rpx;
    max-height: 800rpx;
    padding: 0 30rpx;
  }
  &--btn {
    width: 80%;
    position: absolute;
    bottom: 0rpx;
    left: 10%;
  }
}
</style>
